package XunChunCPU.ID

import chisel3._
import XunChunCPU.common.CommonConfig._

class IDReg extends Module {
    val io = IO(new Bundle {
        val pc_in = Input(UInt(instrAddrLen.W))
        val pc_out = Output(UInt(instrAddrLen.W))
        val instr_in = Input(UInt(instrLen.W))
        val instr_out = Output(UInt(instrLen.W))
        val ready_in = Input(Bool())
        val ready_out = Output(Bool())
        val valid_in = Input(Bool())
        val valid_out = Output(Bool())
        // 译码，执行，访存阶段来的取值暂停信号,当SW或者SB地址为BaseRam时暂停取值的值
        val stallFromIF = Input(Bool())
        val stallFromEXE = Input(Bool())
        val stallFromMEM = Input(Bool())
    })
    io.ready_out := io.ready_in
    val pcreg = RegInit(0.U(instrAddrLen.W))
    val instrreg = RegInit(0.U(instrLen.W))
    val stall = Wire(Bool())
    stall := io.stallFromEXE || io.stallFromMEM || io.stallFromIF
    when(io.ready_in && !stall){
        // IF可接收数据
        pcreg := io.pc_in
        instrreg := io.instr_in
    }.elsewhen(io.ready_in && stall){
        // 仅当译码阶段SW或SB确定要访问baseram时，让行，否则传原值，此处validout也需要更改
        when(io.stallFromIF){
            // 需要传nop
            pcreg := io.pc_out
            instrreg := 0.U(32.W)
        }.otherwise{
            pcreg := io.pc_out
            instrreg := io.instr_out
        }
    }.otherwise{
        pcreg := io.pc_out
        instrreg := io.instr_out
    }
    io.pc_out := pcreg
    io.instr_out := instrreg
    when(io.stallFromIF){
        io.valid_out := true.B
    }.otherwise{
        io.valid_out := io.valid_in
    }
}